perm filename NOTES.PRJ[LSP,JRA]9 blob
sn#307113 filedate 1977-09-27 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00004 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .SEC(Projects)
C00010 00003 .SS(Pretty-printing,,P226:)
C00020 00004 .REQUIRE "NOTES.SDP" SOURCE_FILE
C00034 ENDMK
C⊗;
.SEC(Projects)
.FP
This chapter consists of a set of non-trivial projects which either apply LISP
or extend LISP by adding new language features.
.SS(Extensions to %3eval%*,%3eval%*,P67:)
.SELECT 1;
.BEGIN TURN ON "#";
This next extension to %3eval%* was derived from the syntax of
⊗→MUDDLE↔←⊗↑[Mud#75]↑, ⊗→CONNIVER↔←⊗↑[Con#73]↑, and
⊗→MICRO-PLANNER↔←⊗↑[Mic#71]↑.
We have seen that LISP calling sequences are of two varieties: either
evaluate %6all%* of the arguments; or evaluate %6none%* of the
arguments.
In an attempt to generalize this regime we might allow the evaluation of some
of the arguments and enlarge on the domain
of objects which can appear in the list of λ-variables.
We might partition the formal parameters into required parameters, optional
parameters, and an excess collector to handle any actual parameters left over.
Required parameters %6must%* have corresponding actual parameters; optional
actual parameters are used if present, otherwise declared default
values are used.
If there are more actual parameters than the formals encompassed by the first
two classes, then they are associated with the excess collector.
.GROUP;
To be more precise consider the following possible BNF equations:
.BEGIN TABIT1(15);TURN OFF "←";
.BOXA
<varlist>\::=[<required> <optional> <excess>]
.PT2
<required>\::= <par>; ...;<par> | %9ε%* ⊗↓The symbol "%9ε%1" stands for the empty string.←
.PT2
<optional>\::= "optional" <opn>; ...; <opn> | %9ε%*
.PT2
<excess>\::= "excess" <par> | %9ε%*
.PT2
<par>\::= <variable> | %9`%*<variable>
.PT2
<opn>\::= <par> | <par> ← <form>
.BOXB
.END
.APART
.GROUP;
.FP
The associated semantics are as follows:
.BEGIN TURN OFF "←";
.NL;
%21.%*##The formal parameters are to be bound to the actual parameters from
left to right as usual.
.NL
%22.%*##There must be an actual parameter for each required parameter, and
if there is no excess collector there may not be more actual parameters than
formals. (There may be fewer if we have optionals.)
.NL
%23.%*##If a <variable> in a formal parameter is preceded by a "%9`%*", then
the corresponding actual parameter is %6not%* evaluated. This is just the
%3quote%1-ing %3read%1 macro.
.NL
%24.%*##We might run out of actual parameters while binding the optionals.
If we do, then we look at the remaining formal optionals.
If a formal parameter is simply a <par> then we bind it to %3(#)%*; if a formal is
%9`%1<variable> ← <form> then we bind the <variable> to the <form>;
and if the formal is
<variable> ← <form>, we bind <variable> to the value of <form>, where the
evaluation is to take place %6after%1 the required parameters have been bound.
.NL
%25.%*##Finally, the excess collector is bound to a list of any remaining
actual parameters in the obvious way: if <par> is <variable> then
using the calling environment, form a list
of the values of the remaining arguments;
if it is %9`%1<variable>, bind <variable> to the
actual list. If there is no excess, bind to %3NIL%*.
.PT2
.END
.APART
.BEGIN TURN OFF "←";
We will also extend %3prog%*-variables slightly, allowing
them to be initialized explicitly. If a %3prog%*-variable is atomic,
intialize it to %3(#)%*, as usual. If it is of the form <variable>#←#<form>
then initialize it to the value of the <form>.
.END
.END
.BEGIN TURN OFF "←";turn on "\"; tabs 14,24;
Here are some examples:
.PT2
1.##In the initialization of %3length%* on {yon(P45)}, we could write:
.BEGIN CENTER;turn off "←";
%3...#prog[[l#←#x;#c#←#0]#....%*
.END
.NL
2.##%3list%* could now be defined as: %3λ[[%1"excess"%* x]x]%*.
.NL
3.##Consider the following definition:
.BEGIN NOFILL;
.group
.BOXA
\%3baz <= λ[\[x;%9`%*y;%1"optional"%* z; u ← 0; %1"excess"%* v]
\\print[x];
\\print[y];
\\print[z];
\\print[u];
\\print[v] ]
.BOXB
.APART
.GROUP
.FP
%1Then a call of:
.PT2
.BEGIN TABIT1(7);
%3eval[\(BAZ 2 (CAR (QUOTE (X Y))) 4 5 6 7 (CAR (QUOTE (A . B))));
\NIL]%1
.END
.PT2
.FP
.SELECT 1;
would print:%3 \\2
\\(CAR(QUOTE (X Y)))
\\4
\\5
\\(6 7 A)%*
.FP
and return value: %3(6 7 A)%*.
.APART
.PT2
.GROUP
.FP
Similarly, defining:
.BOXA
\%3fii <= λ[\[x;y;%1"optional"%* z; u ← 0; %1"excess"%3 v]
\\print[x];
\\print[y];
\\print[z];
\\print[u];
\\print[v]].
.BOXB
.BEGIN CENTERit;
.FP
%1and calling: ←%3eval[(FII 2 (CAR (QUOTE (X Y)));NIL]%*
.END
.PT2
.FP
.SELECT 1;
prints:%3\\2
\\X
\\NIL
\\0
\\NIL.%*
.END
.END
.PT2
.CENT(Problem);
.FP
Design simple S-expr representations of these proposed constructs.
Make these extensions to %3eval%*.
.SS(Pretty-printing,,P226:)
.FP
This project expands on the basic notion of "pretty-printing" which
was introduced on {yon(P245)}⊗↓Pretty printers are called
"grinders" at MIT.←. The content of this section introduces
several possible considerations involved in designing asuch a pretty
printer. The intent of this section is for you to take these suggestions and
develop a suitable program based on the suggestions and your experience
with your locally available prettry printer.
The formats described in this section were extracted form ⊗↑[Gol#73]↑.
.GROUP;
.BOXA
.FP
I. %2Linear format%1: The minimal acceptable output format is that produced by %3print%1.
Acceptability is judged by whether that output can be read back into the
machine and have a structure %3equal%1 the the structure printed out⊗↓We
must hedge that a bit, since %3gensym%1 atoms are not placed on the
object list.←.
.APART
.GROUP;
.BOXA
.FP
II. %2Standard format%1: Given a list %3(%7a b c %1...%7 d%3)%1 the standard format
will assume that we are trying to print a function application and will producce:
.BEGIN GROUP;TABIT2(20,24);
.PT2
\%3(%7a\b
\\c
\\ %1. . .%7
\\d%3)
.BOXA
.END
.FP
Thus %3(FOO (CAR (CONS (QUOTE A) B)) (G (H A) 4))%1 would produce:
.PT2
.BEGIN GROUP;TABS 20,27,30,43;NOFILL;TURN ON "\";
.PT2
\%3(FOO\(CAR (CONS\(QUOTE A)
\\\\B))
\\(G\(H A)
\\\4))
.END
.PT2;
.FP
Note that the "standard format" is recursively applied, and thus
may become too wide for the output device. It that case we can resort to the
following format.
.APART
.GROUP;
.BOXA
.FP
III. %2Miser format%1: Write a list %3(%7a b c %1...%7 d%3)%1 as:
.BEGIN GROUP;TABIT2(20,22);
.PT2
\%3(%7a
\ b
\ c
\ %1. . .%7
\ d%3)
.PT2
.END
.FP
Again, the recursive application of this format can overflow the output
width. In that case we may have to resort to "linear format".
.APART;
.GROUP;
Typical pretty printers also recognize certain LISP constructs
and "grind" them differently. That is, we build some semantic knowledge into the
grinder. Block format is useful in many of these contexts.
.BOXA
.FP
IV. %2Block format%1: A list %3(%7a%41%1#...#%7a%4n-1%1,#...#%7a%4n%3)%1
has the block format:
.BEGIN TABIT2(20,21);
.PT2
\%3(\%7a%41%1#...#%7a%4n-1%1
\\%7a%4n%1#...#%7a%4n%3)%1
.PT2
.END
.FP
For example, the list representation of a %3prog%1 might be "ground"
with its %3prog%1 variables in block format and special indenting
in the %3prog%1#body to set off the labels.
The representation of %3length%1 given on {yon(P250)} illustrates
the special format for %3prog%1s, though the %3prog%1#variable list is
not sufficently long to require block format.
.APART
.GROUP;
Another list format which is treated specially is the representation of
a λ-expression.
.BEGIN GROUP;TABIT2(15,28);
.BOXA
\%3(LAMBDA\%1<λ-list ground in block format>
.PT2
\\<body ground as a block>%3)
.BOXA
.END
The example on {yon(P250)} also illistrates this.
This format will allow multiple-bodied λ-expressions.
For example:
.BEGIN SELECT 3; NOFILL;TURN ON "\";TABS 15,28,37
.PT2
\(LAMBDA\(X Y Z)
\\(CONS\X
\\\(QUOTE A))
\\(H 1 2))
.PT2
.END
.APART
.FP
Notice that we decided to write %3(H 1 2)%1 in linear format
rather than standard format; somehow it "looks better". Personal
taste plays a strong role in pretty printing, so several
grinders give the users the ability to describe their own
formats. We will see a similar, but more general device
in {yonss(P105)}. Another possibility for user extension
lies with our property list evaluator of {yonss(P237)}.
Part of the definition of the various LISP constructs would
allow the specification of output conventions for instances
of those constructs; thus besides specifying evaluation properties
for %3LAMBDA%1, %3PROG%1, and %3COND%1, we would also the
grinding routines for outputting instances of those constructs.
.GROUP;
Since lists beginning with %3COND%1 are representations of
conditional expressions they too are handled specially
by the grinding routines.
.BEGIN TABIT2(15,24);
.BOXA
\%3(COND%1\<grind clause%41%1>
.PT2
\\ . . .
.PT2
\\<grind clause%4n%1>%3)
.BOXB
.END
.APART
.FP
These selected formats should give a reasonable idea of the techniques available
for pretty printers. More techniques can be extracted from your local grinder.
.GROUP;
Your pretty printer may assume the existence of %3patom%1, %3print%1, and
%3terpri%1 of {yonss(P13)}; and you may assume the existence of
the usual class of arithmetic operations. In addition, the following
formatting primitives may be used:
.BOXA
.BEGIN INDENT 0,15;GROUP;
%21.%1##%3linelength%1: If %3linelength%1 is called without an argument
then the value returned is the number of characters allowed on a
line of the current output device. If %3linelength%1 is called with
a numeric argument, then the line length of the output device is set to that
number.
.END
.APART
.BOXA
.BEGIN INDENT 0,11;GROUP;
%22.%1##%3chrct%1: This is a nullary function, and returns
a number representing the number of character positions remaining on the current
line. For example, just after %3terpri[]%1 has been executed
.BEGIN NOFILL; indent 11,11;
%3chrct[]#=#linelength[]%1,
and %3prog%42%3[patom[ABC];#difference[linelength[];chrct[]]]#=#3%1.
.END
.END
.BOXA
.BEGIN INDENT 0,14;GROUP;
%23.%1##%3flatsize%1:
A simple count of the
atoms and special characters in an expression won't give an accurate
picture of the requirements for printing an expression.
Special characters take one character position, but
literal atoms and numbers may require more.
To determine whether or not a special format can be used on an expression
requires knowledge of its character count. The number of characters
in the atom %3x%1 is given by %3flatsize[x]%1;
%3flatsize[ABCD]%1 is %34%1. Actually %3flatsize%1 is defined
for non-atomic arguments, giving the number of character positions
required to %3print%1 its argument. For example %3flatsize[(A.B)]%1
is %37%1 rather than %35%1 since %3print%1 will surround the
dot with spaces.
.END
.REQUIRE "NOTES.SDP" SOURCE_FILE;